home *** CD-ROM | disk | FTP | other *** search
- /*
- * CBLibrary - err
- * Copyright (C) 2003 Chris Bazley
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
- /* Original version by Tony Houghton for !FormText
- 07.05.01 CJB - records errors for SFtoSpr
- 08.06.01 CJB - error block made global to save space
- 03.07.01 CJB - needs messages "IntErr1", "IntErr2"
- 25.07.01 CJB - considerable optimisation of fancy message construction
- - uses RISC OS 3.5 extensions
- - No longer tries to prepend "Internal Error" (pretentious)
- 04.10.01 CJB - removed strncpycr() 'cos saw no real need for it
- - made various variables static and publicised others
- 12.12.01 CJB - Removed calls to msgs_lookup() to prevent re-entrancy
- via err_check()
- - Failure to find message tokens is now fatal error reported in
- simplest possible manner.
- 14.12.01 CJB - Functions that construct errors now use a local erblk
- 25.05.02 CJB - Added signal handler and separate fancy fatal error message.
- 13.11.02 CJB - Separate signal handler for SIGSTAK that uses static error
- message and doesn't perform stack limit checking
- 14.11.02 CJB - Removed signal handlers, since new C Library does a better job.
- 27.04.03 CJB - erblk was unnecessarily being inited twice in err_complain().
- No return from err_box_die().
- err_box_continue() only returns if 'Continue' selected .
- A tiddly bit smaller.
- 05.08.03 CJB - eliminated strcpy(x, "") in favour of fast x[0] = '/0';
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdbool.h>
-
- #include "wimplib.h"
- #include "kernel.h"
- #include "swis.h"
- #include "err.h"
- #include "msgtrans.h"
-
- #define Wimp_ReportError_UseCategory (1u << 8)
-
- #ifndef NO_RECORD_ERR
- static bool suppress_errors = false;
- static _kernel_oserror recorded_error;
- #endif
- static bool riscos_350 = false;
- static char err_taskname[32] = "application";
-
- /* ----------------------------------------------------------------------- */
- /* Function prototypes */
-
- static void fancy_error(_kernel_oserror *dest_block, const int errnum, const char *errmess, bool fatal);
- static void err_box_continue(_kernel_oserror *errblk);
-
- /* ----------------------------------------------------------------------- */
- /* Public functions */
-
- #ifndef NO_RECORD_ERR
- void err_suppress_errors(void)
- {
- suppress_errors = true;
- recorded_error.errnum = 255;
- recorded_error.errmess[0] = '\0';
- }
-
- /* ----------------------------------------------------------------------- */
-
- _kernel_oserror *err_dump_suppressed(void)
- {
- suppress_errors = false;
- if(strcmp(recorded_error.errmess, "") == 0)
- return NULL;
- return &recorded_error;
- }
- #endif
-
- /* ----------------------------------------------------------------------- */
-
- void err_set_taskname(const char *name, bool new_errs)
- {
- strncpy(err_taskname, name, sizeof(err_taskname)-1);
- riscos_350 = new_errs;
- }
-
- /* ----------------------------------------------------------------------- */
-
- bool err_check(const _kernel_oserror *er)
- {
- if(er == NULL) {
- return false;
- }
- else {
- err_check_rep(er);
- return true;
- }
- }
-
- /* ----------------------------------------------------------------------- */
-
- void err_check_rep(const _kernel_oserror *er)
- {
-
- #ifndef NO_RECORD_ERR
- /* Should we preserve the error for posterity? */
- if(suppress_errors) {
- suppress_errors = false;
- recorded_error = *er;
- }
- else {
- #endif
- _kernel_oserror erblk;
- fancy_error(&erblk, er->errnum, er->errmess, false);
- err_box_continue(&erblk);
- #ifndef NO_RECORD_ERR
- }
- #endif
- }
-
- /* ----------------------------------------------------------------------- */
-
- void err_check_fatal_rep(const _kernel_oserror *er)
- {
- _kernel_oserror erblk;
-
- fancy_error(&erblk, er->errnum, er->errmess, true);
- err_box_die(&erblk);
- }
-
- /* ----------------------------------------------------------------------- */
-
- void err_report(int num, const char *mess)
- {
-
- #ifndef NO_RECORD_ERR
- /* Should we preserve the error for posterity? */
- if(suppress_errors) {
- suppress_errors = false;
- recorded_error.errnum = num;
- strncpy(recorded_error.errmess, mess, sizeof(recorded_error.errmess)-1);
- }
- else {
- #endif
- _kernel_oserror erblk;
- erblk.errnum = num;
- strncpy(erblk.errmess, mess, sizeof(erblk.errmess)-1);
- wimp_report_error(&erblk, Wimp_ReportError_OK, err_taskname);
- #ifndef NO_RECORD_ERR
- }
- #endif
- }
-
- /* ----------------------------------------------------------------------- */
-
- void err_complain(int num, const char *mess)
- {
-
- #ifndef NO_RECORD_ERR
- /* Should we preserve the error for posterity? */
- if(suppress_errors) {
- suppress_errors = false;
- recorded_error.errnum = num;
- strncpy(recorded_error.errmess, mess, sizeof(recorded_error.errmess)-1);
- }
- else {
- #endif
- _kernel_oserror erblk;
- fancy_error(&erblk, num, mess, false);
- err_box_continue(&erblk);
- #ifndef NO_RECORD_ERR
- }
- #endif
- }
-
- /* ----------------------------------------------------------------------- */
-
- void err_complain_fatal(int num, const char *mess)
- {
- _kernel_oserror erblk;
-
- fancy_error(&erblk, num, mess, true);
- err_box_die(&erblk);
- }
-
- /* ----------------------------------------------------------------------- */
- /* Private functions */
-
- static void fancy_error(_kernel_oserror *dest_block, const int errnum, const char *errmess, bool fatal)
- {
- char *token;
-
- if(fatal) {
- token = "FatErr";
- }
- else {
- if(riscos_350)
- token = "NewErr";
- else
- token = "OldErr";
- }
- _kernel_oserror *lookup_err = _swix(MessageTrans_Lookup, _INR(0,4), msgs_get_descriptor(), token, dest_block->errmess, sizeof(dest_block->errmess), errmess);
- if(lookup_err != NULL) {
- wimp_report_error(lookup_err, Wimp_ReportError_Cancel, err_taskname);
- exit(EXIT_FAILURE); /* Failure to find our messages is fatal! */
- }
- dest_block->errnum = errnum;
- }
-
- /* ----------------------------------------------------------------------- */
-
- static void err_box_continue(_kernel_oserror *errblk)
- {
- if(riscos_350) {
- /* Nice error box */
- char err_buttons[32];
- _kernel_oserror *lookup_err = _swix(MessageTrans_Lookup, _INR(0,3), msgs_get_descriptor(), "ErrButtons", err_buttons, sizeof(err_buttons));
- if(lookup_err != NULL) {
- /* Failure to find our messages is fatal! */
- wimp_report_error(lookup_err, Wimp_ReportError_Cancel, err_taskname);
- } else {
- if(wimp_report_error(errblk, Wimp_ReportError_OK|Wimp_ReportError_UseCategory, err_taskname, NULL, NULL, err_buttons) == Wimp_ReportError_OK)
- return; /* we live on */
- }
- } else {
- /* Backwards compatibility */
- if(wimp_report_error(errblk, Wimp_ReportError_OK|Wimp_ReportError_Cancel, err_taskname) == Wimp_ReportError_OK)
- return; /* we live on */
- }
- exit(EXIT_FAILURE); /* die (message not found, or user quit) */
- }
-
- /* ----------------------------------------------------------------------- */
-
- void err_box_die(_kernel_oserror *errblk)
- {
- if(riscos_350) {
- /* Nice error box */
- char err_buttons[32];
- _kernel_oserror *lookup_err = _swix(MessageTrans_Lookup, _INR(0,3), msgs_get_descriptor(), "ErrButtons", err_buttons, sizeof(err_buttons));
- if(lookup_err != NULL)
- wimp_report_error(lookup_err, Wimp_ReportError_Cancel, err_taskname);
- else
- wimp_report_error(errblk, Wimp_ReportError_UseCategory, err_taskname, NULL, NULL, err_buttons);
- }
- else {
- /* Backwards compatibility */
- wimp_report_error(errblk, Wimp_ReportError_Cancel, err_taskname);
- }
- exit(EXIT_FAILURE);
- }
-